package birdsong.server;


import java.util.ArrayList;
import java.util.LinkedList;

import javax.swing.JOptionPane;

import birdsong.comm.implemented.ServerSideMessage;
import birdsong.comm.interfaces.ServerComm;

public class MessageFilter implements ServerComm {
	
	
	private ServerComm    decoratedServerComm;
	
	private LinkedList<User> users= new LinkedList<User>();
	private User actualuser;
	private ArrayList<User>   banUsers =new ArrayList<User>() ;
	
	/**
	 * Create the message filter.
	 * 
	 * @param decoratedServerComm the server comm interface to decorate
	 * @param sensitiveWords the words which the filter should check messages for. 
	 *         If a Birdsong message from a client matches any of the words in the array,
	 *         it is rejected.
	 */
	
	public MessageFilter(ServerComm decoratedServerComm) {
		this.decoratedServerComm = decoratedServerComm; 
		
		
	}
	
	@Override
	public void start() {
		//decoratedServerComm.start();
		getNextMessage();
	}

	@Override
	public ServerSideMessage getNextMessage() {
		
		boolean allow;
		ServerSideMessage message;
		do {
			allow   = true;
			message = (ServerSideMessage) decoratedServerComm.getNextMessage();
			if (message != null && userPresentBanList(message.getClientNickname(), System.currentTimeMillis())) 
			{
				actualuser=new User(message,System.currentTimeMillis());
				if (message.getType() == ServerSideMessage.Type.BIRDSONG_MESSAGE ){
					verify30sec_10messages_RepeatedMessages();
					
				}	
			}
			
		} while (!allow);
		return message;
	}

	
	/**
	 * Verify30sec_10messages_repeatedMessages();
	 * 
	 * Variable aux-> serves as a counter for the 10 mesages in 30 seconds.
	 * Variable repeated-> if a message is repeated in the 30 sec, counts it.
	 *  
	 *  If the variable aux and repeated get to close to the limit of the filter (2 messages repeated or 8 messages in 30sec), 
	 *  gives the user a warning that he is about to get disconnected.
	 *  once the limit is reach the user is disconnected and added to the ban-list that holds users that have send messages 
	 *  in the 30 seconds. 
	 * 
	 * 
	 *   
	 * @author 30525
	 *
	 */

	private void verify30sec_10messages_RepeatedMessages() {
		int aux=1;
		int repeated=1;
		
		for(User user: users){
			if(user.getNickName().equals(actualuser.getNickName()) && actualuser.getTimeStamp()-user.getTimeStamp()<=30000){
				aux++;	
				if(user.getmessageContent().equals(actualuser.getmessageContent())){
					repeated++;
				}
				
			}
		}
		System.out.print(aux);
		if(aux==10 || repeated==3){
			DisconnectUsers();
			banUsers.add(actualuser);
		}else if(aux==8 || repeated==2){
			decoratedServerComm.sendBirdsongMessage("SpamFilter", actualuser.getNickName(), "Warning to many messages");
			
			users.add(actualuser);
		}else{
			users.add(actualuser);
			
		}
		
	}

	/**
	 * DisconnectUsers();
	 * 
	 * Removes the user from the users list and warnes the user that he as been disconnected.
	 * 
	 *   
	 * @author 30525
	 *
	 */
	private void DisconnectUsers() {
		// TODO Auto-generated method stub
		for(int i=0; i<users.size(); i++){
			if(users.get(i).getNickName() == actualuser.getNickName()){
					users.remove(i);
			}
		}
		disconnectClient(actualuser.getNickName());
		JOptionPane.showMessageDialog(null, "User "+actualuser.getNickName()+" Disconnect!");
	}

	
	/**
	 * userPresentBanList(String string, long l)
	 * @param String string->Name of the user in search;
	 * @param long l-> mili seconds of the user when checked if he is the list;
	 * 
	 * Search for the user in the ban list and remove it.
	 *   
	 * @author 30525
	 *
	 */
	private boolean userPresentBanList(String string, long l) {

		boolean bool = false;
		for (int i=0; i<banUsers.size(); i++){
			if(banUsers.get(i).getNickName().equals(string) && l-banUsers.get(i).getTimeStamp()>30000 ){
				bool=true;
				banUsers.remove(i);
			}	
		}
		if(banUsers.isEmpty())
			return true;
		return bool;
	}

	@Override
	public boolean hasNextMessage() {
		return decoratedServerComm.hasNextMessage();
	}

	@Override
	public void sendBirdsongMessage(String fromNicename, String toNickname,
			String birdsongMessage) {
		decoratedServerComm.sendBirdsongMessage(fromNicename, toNickname, birdsongMessage);
	}

	@Override
	public void sendNewFollower(String toNickname, String newFollower) {
		decoratedServerComm.sendNewFollower(toNickname, newFollower);
	}

	@Override
	public void sendNewUnfollow(String toNickname, String unfollower) {
		decoratedServerComm.sendNewUnfollow(toNickname, unfollower);
		
	}

	@Override
	public void sendError(String toNickname, String error) {
		decoratedServerComm.sendError(toNickname, error);
	}

	@Override
	public void sendClientConnected(String toNickname, String connectedNickname) {
		decoratedServerComm.sendClientConnected(toNickname, connectedNickname);
	}

	@Override
	public void sendClientDisconnected(String toNickname,
			String disconnectedNickname) {
		decoratedServerComm.sendClientDisconnected(toNickname, disconnectedNickname);
		
	}

	@Override
	public boolean clientIsConnected(String nickname) {
		return decoratedServerComm.clientIsConnected(nickname);
	}

	@Override
	public void disconnectClient(String nickname) {
		decoratedServerComm.disconnectClient(nickname);
	}

}

